#include "Grid.h"

#ifdef DX9

#include "NeroCore\NMemoryManager.h"
#include "NeroEngine\NArchive.h"
#include "NeroGame\NGame.h"

#if WIN_32
#include "Win32_DX9\Win32ColorHelper.h"
#include "Win32_DX9\Win32Platform.h"
#include "Win32_DX9\Win32Device.h"
#endif

using namespace Graphics;

RTTI_DEFINITIONS(Grid);

Grid::Grid()
	:Win32RenderEntity(),
	 mSize(DEFAULT_SIZE),
	 mDivisions(DEFAULT_DIVISIONS),
	 mVertices(NULL)
{
}

Grid::Grid(int size, int division)
	:Win32RenderEntity(),
	 mSize(size),
	 mDivisions(division),
	 mVertices(NULL)
{
}

Grid::~Grid(void)
{
	mEnabled = false;

	if(mVertices != NULL)
	{
		MY_DELETE_ARRAY(mVertices);
		mVertices = NULL;
	}
}

void Grid::Initialize()
{	
	Game::NEvent<int>::Subscribe(this);

	Populate();

	Core::NDatum* SizeDatum = Find("Size");
	if(SizeDatum)
	{
		mSize = SizeDatum->Get<int>(0);
	}

	Core::NDatum* DivisionsDatum = Find("Divisions");
	if(DivisionsDatum)
	{
		mDivisions = DivisionsDatum->Get<int>(0);
	}

	mDistBetweenSections = mSize / mDivisions;
	mNumPrimatives = (mDivisions+1)*2;
	mNumVerts = mNumPrimatives*2;

	mVertexBuffer.Initialize(mNumVerts);

	mEnabled = true;
	
	mVertices = MY_NEW(Memory::HID_Dynamic,"Verts") Graphics::CUSTOMVERTEX[mNumVerts];

	float xPosition = (float)-mSize/2;
	int i = 0;
	for(; i < mNumVerts/2; i += 2)
	{
		//Point 1
		Graphics::SetCustumVertex(&mVertices[i],D3DXVECTOR3(xPosition, 0.0f, (float)mSize/2), Win32ColorHelper::White);

		//Point 2
		Graphics::SetCustumVertex(&mVertices[i+1],D3DXVECTOR3(xPosition, 0.0f, (float)-mSize/2), Win32ColorHelper::White);

		xPosition += mDistBetweenSections;
	}

	float zPosition = (float)-mSize/2;
	for(int j = i;j < mNumVerts; j += 2)
	{
		//Point 1
		Graphics::SetCustumVertex(&mVertices[j],D3DXVECTOR3((float)mSize/2, 0.0f, zPosition), Win32ColorHelper::White);

		//Point 2
		Graphics::SetCustumVertex(&mVertices[j+1],D3DXVECTOR3((float)-mSize/2, 0.0f, zPosition), Win32ColorHelper::White);
		zPosition += mDistBetweenSections;
	}

	mVertexBuffer.Lock();
	mVertexBuffer.SetVertices(mVertices);
	mVertexBuffer.Unlock();
}

void Grid::Update(float gameTime)
{
}

void Grid::Render(float gameTime)
{
	if(mEnabled)
	{
		System::Win32Platform* platform = GetPlatform();
		if(platform != NULL)
		{
			LPDIRECT3DDEVICE9 device = platform->GetDevice()->GetDevice();
			if(device != NULL)
			{
				device->SetRenderState(D3DRS_LIGHTING, FALSE );
				device->SetFVF(CUSTOMFVF3D);									// select which vertex format we are using
	
				device->SetTexture(0,NULL);
				mVertexBuffer.Render(device);
				device->DrawPrimitive(D3DPT_LINELIST, 0, mNumPrimatives);
			}
		}
	}
}

void Grid::Populate()
{
	mSignatures.push_back(Signature("DistanceBetweenSections", Core::NDatum::eTYPE_INT, &mDistBetweenSections, 1 ,&mDistBetweenSections));
	mSignatures.push_back(Signature("NumberOfPrimatives", Core::NDatum::eTYPE_INT, &mNumPrimatives, 1 ,&mNumPrimatives));
	mSignatures.push_back(Signature("NumberOfVerts", Core::NDatum::eTYPE_INT, &mNumVerts, 1 ,&mDistBetweenSections));

	NAttributed::Populate();
}

void Grid::Notify(Engine::NEventPublisher* aEventPublisher, float wallTime)
{
	D3DXVECTOR3 movement = (D3DXVECTOR3(0,0,0));
	Game::NEvent<int>* e = aEventPublisher->As<Game::NEvent<int>>();
	if(e)
	{
		if(e->GetEventMessage() == 84)
		{
			mEnabled = !mEnabled;
		}
	}
}

int Grid::Serialize(Core::NArchive ar)
{
	int status = Graphics::Win32RenderEntity::Serialize(ar);
	if(status == Core::NArchive::STATUS_SUCCESS)
	{
		ar << mSize;
		ar << mDivisions;

		ar << mDistBetweenSections;
		ar << mNumPrimatives;
		ar << mNumVerts;
	}
	return status;
}

int Grid::Deserialize(Core::NArchive ar)
{
	int status = Graphics::Win32RenderEntity::Serialize(ar);
	if(status == Core::NArchive::STATUS_SUCCESS)
	{
		ar >> mSize;
		ar >> mDivisions;

		ar >> mDistBetweenSections;
		ar >> mNumPrimatives;
		ar >> mNumVerts;
	}
	return status;
}

#endif